import axios from 'axios';
import { Md5 } from 'ts-md5';
import { $fetch } from '@/settings/utils/fetch';
import i18n from '@/settings/i18n';
import mime from 'mime/lite';

export interface UploadOptions {
  onProgress?: (progress: number) => void;
}

const getHashFileName = (file: File) => new Promise<string | boolean>((resolve) => {
  const reader = new FileReader();

  reader.onload = (e: ProgressEvent<FileReader>) => {
    if (e.target?.result) {
      const md5 = new Md5();
      md5.appendByteArray(new Uint8Array(e.target.result as ArrayBuffer));

      const suffix = file.name.slice(file.name.lastIndexOf('.'));

      resolve(`${md5.end() as string}${suffix}`);
    }
    else {
      resolve(false);
    }
  }
  reader.onerror = () => resolve(false);

  reader.readAsArrayBuffer(file);
});

const getUploadSignature = async () => {
  const { isSuccess, data } = await $fetch('/admin/oss/ossInfo');

  return { isSuccess, data };
};

const uploadFile = async (file: File, options: UploadOptions = {}) => {
  const { isSuccess, data } = await getUploadSignature();

  if (!isSuccess) {
    return {
      isSuccess: false,
      msg: i18n.global.t('settings.notification.upload.illegal'),
    };
  }

  const md5Filename = await getHashFileName(file);

  if (!md5Filename) {
    return {
      isSuccess: false,
      msg: i18n.global.t('settings.notification.upload.filenameError'),
    };
  }

  const formData = new FormData();

  formData.append('key', `${data.directory}${md5Filename}`);
  formData.append('OSSAccessKeyId', data.accessKeyId);
  formData.append('policy', data.policy);
  formData.append('signature', data.signature);
  formData.append('success_action_status', '200');
  formData.append('x-oss-content-type', mime.getType(md5Filename as string) ?? 'application/octet-stream');
  formData.append('file', file);

  try {
    const response = await axios.post(data.host, formData, {
      onUploadProgress: (e) => {
        if (e.total) {
          options.onProgress?.((e.loaded / e.total) * 100);
        }
        else {
          options.onProgress?.(100);
        }
      },
    });

    const status = response.status;

    if (status !== 200) {
      return {
        isSuccess: false,
        msg: i18n.global.t('settings.notification.upload.error'),
      };
    }

    return {
      isSuccess: true,
      msg: i18n.global.t('settings.notification.upload.success'),
      url: `${data.url}/${data.directory}${md5Filename}`,
    };
  }
  catch (error: any) {
    if (error.response) {
      return {
        isSuccess: false,
        msg: i18n.global.t('settings.notification.upload.networkError', { msg: error.response.status }),
      };
    }
    else {
      return {
        isSuccess: false,
        msg: i18n.global.t('settings.notification.upload.otherError', { msg: error.message }),
      };
    }
  }
};

export default function useUploader() {
  return {
    uploadFile,
    getUploadSignature,
    getHashFileName,
  };
}
